﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using Utils;
using System.Data;
using Settings;

namespace Business
{
    public class MtQueueRepository
    {
        /// <summary>
        /// Insert dữ liệu vào mt_queue đồng thời gửi tin nhắn đi bằng webservice. Trả về số lượng tin nhắn đã được gửi đi bằng webservice
        /// </summary>
        /// <param name="table">Table chứa dữ liệu cần gửi tin nhắn</param>
        /// <param name="max_adv_senf">số tin nhắn tối đa cho phép gửi đi bằng webservice</param>
        /// <param name="cmd"></param>
        public static int Insert(DataTable table, int max_adv_send, SqlCommand cmd)
        {
            int result = 0;
            try
            {
                if (table.Rows.Count > 0)
                {
                    //Nếu cho phép gửi tin thì dùng webservice để gửi tin 
                    if (LocalSettings.TurnOnSendMessage)
                    {
                        result = SendMessage(table, max_adv_send, cmd);
                    }

                    //Insert dữ liệu vào bảng mt_queue
                    using (SqlBulkCopy bc = new SqlBulkCopy(cmd.Connection))
                    {
                        bc.DestinationTableName = "dbo.mt_queue";
                        bc.BulkCopyTimeout = 0;
                        bc.WriteToServer(table);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        private static DataTable CreateTableSMSOut(DataTable dtInput, int max_adv_send)
        {
            DataTable dt = new DataTable();
            dt.TableName = "SMSOut";
            dt.Columns.Add("DestAddr", typeof(string));
            dt.Columns.Add("ShortCode", typeof(string));
            dt.Columns.Add("Message", typeof(string));
            dt.Columns.Add("CooperateGUID", typeof(string));
            dt.Columns.Add("SmsInGUID", typeof(string));
            dt.Columns.Add("CDRIndicator", typeof(string));
            dt.Columns.Add("MTType", typeof(string));

            foreach (DataRow row in dtInput.Rows)
            {
                string dest_addr = (string)row["dest_addr"];
                if (crm_black_list.DictInstanct.ContainsKey(dest_addr)
                    && crm_black_list.DictInstanct[dest_addr])
                {
                    row["status"] = Status.BANNED;
                }
                else if (dt.Rows.Count < max_adv_send)
                {
                    dt.Rows.Add(dest_addr, row["vasp_num"], row["msg"], row["mt_queue_id"].ToString(), "", "FREE", "normal");
                }
                else
                {
                    row["status"] = Status.OUT_OF_LIMIT;
                }
            }
            return dt;
        }

        public static int Insert(crm_advertisment adv, IDataReader subscriber, SqlCommand cmd)
        {
            using (DataTable table = ObjectClass.CreateTableSchema<mt_queue>())
            {
                table.PrimaryKey = new DataColumn[] { table.Columns["mt_queue_id"] };
                while (subscriber.Read())
                {
                    AddDataRow(table, adv, subscriber);
                }
                subscriber.Close();
                return Insert(table, adv.max_advertisment - adv.sent_advertisment, cmd);
            }
        }

        public static void AddDataRow(DataTable table, crm_advertisment adv, IDataReader subscriber)
        {
            Guid newId = Guid.NewGuid();
            Guid? guid_key;
            try
            {
                guid_key = (Guid)subscriber["guid_key"];
            }
            catch
            {
                guid_key = null;
            }
            ObjectClass.AddDataRow<mt_queue>(table, new mt_queue()
            {
                mt_queue_id = newId,
                deliver_sm_id = 0,
                submit_sm_id = 1,
                date_time = DateTime.Now,
                subs = (string)subscriber["subscriber"],
                dest_addr = (string)subscriber["subscriber"],
                vasp_num = (adv.sender_name == "vasp_num" && adv.action_id == (int)Settings.ActionId.WhenMessageReceived) 
                                                ? subscriber["vasp_num"] as string : adv.sender_name,
                msg = adv.message,
                msg_hex_body = adv.message.ToHex(Encoding.ASCII),
                num_of_concated = 0,
                esm_class = 0,
                isBinary = "0",
                operator_id = subscriber["operator_id"].ToString(),
                gateway_id = subscriber["gateway_id"].ToString(),
                cdr_indicator = "FREE",
                report_id = 0,
                report_guid = newId,
                report_table = "game_mt_log",
                report_table_id_name = "game_mt_log_id",
                mt_flag = "normal",
                retry_on_fail_req_times = 0,
                retry_on_timeout_req_times = 0,
                retry_on_fail_req_duration = 0,
                retry_on_timeout_req_duration = 0,
                mo_guid = null,
                delay_time = 0,
                response_status_field_name = "status",
                sent_time_field_name = "sent_time",
                delivery_receipt_indicator = null,
                smpp_account = null,
                advertisment_id = adv.advertisment_id,
                collection_id = adv.collection_id,
                subscriber_classification_guidkey = guid_key,
                status = Status.PENDING
            });
        }

        private static int SendMessage(DataTable dtSource, int max_adv_send, SqlCommand cmd)
        {
            int result = 0;
            //Sử dụng webservice để gửi tin
            string[][] arrayGuidReturn = new string[][] { };
            string message_return = string.Empty;

            DataTable dtSentSms = CreateTableSMSOut(dtSource, max_adv_send);
            try
            {
                SMSMTService.SentMSM(dtSentSms, ref arrayGuidReturn, ref message_return);
            }
            catch (TimeoutException)
            {
                foreach (DataRow row in dtSentSms.Rows)
                {
                    DataRow dtRow = dtSource.Rows.Find(Guid.Parse((string)row["CooperateGUID"]));
                    if (dtRow != null)
                    {
                        dtRow["status"] = Status.TIMEOUT;
                    }
                }
                return 0;
            }
            catch (Exception)
            {
                foreach (DataRow row in dtSentSms.Rows)
                {
                    DataRow dtRow = dtSource.Rows.Find(Guid.Parse((string)row["CooperateGUID"]));
                    if (dtRow != null)
                    {
                        dtRow["status"] = Status.EXCEPTION;
                    }
                }
                return 0;
            }
            // Neu iResult = 1 => tat ca cac ban ghi duoc gui thanh cong
            // Neu iResult = -1, co loi xay ra, duyet tung phan tu trong 
            // arrayGuidReturn de xac dinh ban ghi thanh cong va khong thanh cong
            //Cập nhật trạng thái cho table theo trạng thái trả về của webservice.
            //Nếu gửi tin thành công: trạng thái là SENT_GATEWAY
            //Nếu gửi tin không thành công: trạng thái là trạng thái trả về của service
            if (arrayGuidReturn.Length > 0 && arrayGuidReturn[0].GetUpperBound(0) >= 0)
            {
                DataTable dt_service_log = MtServiceLogRepository.CreateTableSchema();
                for (int j = 0; j < arrayGuidReturn[0].Length; j++)
                {
                    Guid guid_key = Guid.Parse(arrayGuidReturn[0][j]);
                    string sv_status = arrayGuidReturn[1][j];
                    string status = Status.FAIL_GATEWAY;
                    if (sv_status.Equals("TRUE", StringComparison.CurrentCultureIgnoreCase))
                    {
                        status = Status.SENT_GATEWAY;
                        result++;
                    }
                    DataRow row = dtSource.Rows.Find(guid_key);
                    if (row != null)
                    {
                        row["status"] = status;
                        MtServiceLogRepository.AddDataRow(dt_service_log, row, sv_status);
                    }
                }
                MtServiceLogRepository.Insert(dt_service_log, cmd);
            }
            return result;
        }
    }
}
